PAGE 118,121
TITLE TEST6 ---- 11/15/85  POST TESTS AND SYSTEM BOOT STRAP
.286C
.XLIST
INCLUDE DSEG.INC
INCLUDE POSTEQU.INC
INCLUDE SYSDATA.INC
.LIST
CODE	SEGMENT BYTE PUBLIC

	PUBLIC	BOOT_STRAP_1
	PUBLIC	POST6
	PUBLIC	STGTST_CNT
	PUBLIC	ROM_ERR
	PUBLIC	XMIT_8042

	EXTRN	CMOS_READ:NEAR
	EXTRN	DDS:NEAR
	EXTRN	DISK_BASE:NEAR
	EXTRN	E602:NEAR
	EXTRN	ERR_BEEP:NEAR
	EXTRN	E_MSG:NEAR
	EXTRN	F3A:NEAR
	EXTRN	PRT_SEG:NEAR

	ASSUME	CS:CODE,DS:DATA

POST6	PROC	NEAR
;----------------------------------------------------------------
; THIS SUBROUTINE PERFORMS A READ/WRITE STORAGE TEST ON A BLOCK :
;	OF STORAGE.						:
; ENTRY REQUIREMENTS:						:
;	ES = ADDRESS OF STORAGE SEGMENT BEING TESTED		:
;	DS = ADDRESS OF STORAGE SEGMENT BEING TESTED		:
;	CX = WORD COUNT OF STORAGE BLOCK TO BE TESTED		:
; EXIT PARAMETERS:						:
;	ZERO FLAG = 0 IF STORAGE ERROR (DATA COMPARE OR PARITY	:
;	CHECK). AL=0 DENOTES A PARITY CHECK. ELSE AL=XOR'ED     :
;	BIT PATTERN OF THE EXPECTED DATA PATTERN VS THE ACTUAL	:
;	DATA READ.						:
; AX,BX,CX,DX,DI, AND SI ARE ALL DESTROYED.			:
;----------------------------------------------------------------
STGTST_CNT	PROC	NEAR
	MOV	BX,CX			; SAVE WORD COUNT OF BLOCK TO TEST
	IN	AL,PORT_B
	OR	AL,RAM_PAR_OFF		; TOGGLE PARITY CHECK LATCHES
	OUT	PORT_B,AL		; TO RESET ANY PENDING ERROR
	AND	AL,RAM_PAR_ON
	OUT	PORT_B,AL

;-----	ROLL A BIT THROUGH THE FIRST WORD

	XOR	DX,DX			; CLEAR THE INITIAL DATA PATTERN
	MOV	CX,16			; ROLL 16 BIT POSITIONS
	SUB	DI,DI			; START AT BEGINNING OF BLOCK
	SUB	SI,SI			; INITIALIZE DESTINATION POINTER
	STC				; SET CARRY FLAG ON FOR FIRST BIT
C1:
	RCL	DX,1			; MOVE BIT OVER LEFT TO NEXT POSITION
	MOV	[DI],DX 		; STORE DATA PATTERN
	MOV	AX,[DI] 		; GET THE DATA WRITTEN
	XOR	AX,DX			; INSURE DATA AS EXPECTED [CLEAR CARRY)
	LOOPZ	C1			; LOOP TILL DONE OR ERROR

	JNZ	C13			; EXIT IF ERROR

;-----	CHECK CAS LINES FOR HIGH BYTE LOW BYTE

	MOV	DX,0FF00H		; TEST DATA - AX= 0000H
	MOV	[DI],AX 		; STORE DATA PATTERN = 0000H
	MOV	[DI+1],DH		; WRITE A BYTE OF FFH AT ODD LOCATION
	MOV	AX,[DI] 		; GET THE DATA - SHOULD BE 0FF00H
	XOR	AX,DX			; CHECK THE FIRST WRITTEN
	JNZ	C13			; ERROR EXIT IF NOT ZERO

	MOV	[DI],AX 		; STORE DATA PATTERN OF 0000H
	MOV	[DI],DH 		; WRITE A BYTE OF FFH AT EVEN LOCATION
	XCHG	DH,DL			; SET DX= 000FFH AND BUS SETTLE
	MOV	AX,[DI] 		; GET THE DATA
	XOR	AX,DX			; CHECK THE FIRST WRITTEN
	JNZ	C13			; EXIT IF NOT

;-----	CHECK FOR I/O OR BASE MEMORY ERROR

	IN	AL,PORT_B		; CHECK FOR I/O - PARITY CHECK
	XCHG	AL,AH			; SAVE ERROR
	IN	AL,DMA_PAGE+6		; CHECK FOR R/W OR I/O ERROR
	AND	AH,AL			; MASK FOR ERROR EXPECTED

;-----	PARITY ERROR EXIT

	MOV	AX,0			; RESTORE AX TO 0000
	JNZ	C13			; EXIT IF PARITY ERROR

	MOV	DX,0AA55H		; WRITE THE INITIAL DATA PATTERN
C3:
	SUB	DI,DI			; START AT BEGINNING OF BLOCK
	SUB	SI,SI			; INITIALIZE DESTINATION POINTER
	MOV	CX,BX			; SETUP BYTE COUNT FOR LOOP
	MOV	AX,DX			; GET THE PATTERN
	REP	STOSW			; STORE 64K BYTES (32K WORDS)
	MOV	CX,BX			; SET COUNT
	SUB	SI,SI			; START AT BEGINNING
C6:
	LODSW				; GET THE FIRST WRITTEN
	XOR	AX,DX			; INSURE DATA AS EXPECTED
	LOOPZ	C6			; LOOP TILL DONE OR ERROR

	JNZ	C13			; EXIT IF NOT EXPECTED (ERROR BITS ON)

;-----	CHECK FOR I/O OR BASE MEMORY ERROR

	IN	AL,PORT_B		; CHECK FOR I/O - PARITY CHECK
	XCHG	AL,AH			; SAVE ERROR
	IN	AL,DMA_PAGE+6		; CHECK FOR R/W OR I/O ERROR
	AND	AH,AL


;-----	PARITY ERROR EXIT

	MOV	AX,0			; RESTORE AX TO 0000
	JNZ	C13			; GO IF YES

;-----	CHECK FOR END OF 64K BLOCK

	AND	DX,DX			; ENDING ZERO PATTERN WRITTEN TO MEMORY?
	JZ	C13			; YES - RETURN TO CALLER WITH AL,0

;-----	SETUP NEXT PATTERN

	CMP	DX,055AAH		; CHECK IF LAST PATTERN =55AA
	JZ	C9			; GO IF NOT
	CMP	DX,0101H		; LAST PATTERN 0101?
	JZ	C10			; GO IF YES
	MOV	DX,055AAH		; WRITE 55AA TO STORAGE
	JMP	C3

;-----	INSURE PARITY BITS ARE NOT STUCK ON

C9:	MOV	DX,0101H		; WRITE 0101 TO STORAGE
	JMP	C3

;-----	EXIT STORAGE TEST
C13:
	RET				; ERROR IF ZF NOT SET

;-----	CHECKER BOARD TEST

C10:	SUB	DI,DI			; POINT TO START OF BLOCK
	MOV	CX,BX			; GET THE BLOCK COUNT
	SHR	CX,1			; DIVIDE BY 2
	MOV	AX,1010101010101010B	; SECOND CHECKER PATTERN
	MOV	SI,0101010101010101B	; FIRST CHECKER PATTERN
C11:
	XCHG	AX,SI			; FIRST CHECKER PATTERN TO AX
	STOSW				; WRITE IT TO MEMORY
	XCHG	AX,SI			; SECOND CHECKER PATTERN TO AX
	STOSW				; WRITE IT TO MEMORY
	LOOP	C11			; DO IT FOR CX COUNT

	SUB	SI,SI			; POINT TO START OF BLOCK
	MOV	CX,BX			; GET THE BLOCK COUNT
	SHR	CX,1			; DIVIDE BY 2
	MOV	DI,0101010101010101B	; CHECK CORRECT
	MOV	DX,1010101010101010B
C12:
	LODSW				; GET THE DATA
	XOR	AX,DI			; CHECK CORRECT
	JNZ	C13			; EXIT IF NOT

	LODSW				; GET NEXT DATA
	XOR	AX,DX			; CHECK SECOND PATTERN
	LOOPZ	C12			; CONTINUE TILL DONE

	JNZ	C13			; ERROR EXIT IF NOT CORRECT

;-----	CHECK FOR I/O OR BASE MEMORY PARITY CHECK

	IN	AL,PORT_B		; CHECK FOR I/O-PARITY CHECK
	XCHG	AL,AH			; SAVE ERROR
	IN	AL,DMA_PAGE+6		; CHECK FOR R/W OR I/O ERROR
	AND	AH,AL

;-----	CHECKPOINT 32 FOR ADDRESS LINE 0->15 FAILURE

	MOV	AL,32H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  32 <><>
	MOV	AX,0			; RESTORE AX (SET AX TO ZERO)
	JNZ	C13			; EXIT IF PARITY ERROR

;-----	64K ADDRESS TEST AND FILL WITH ZERO

	DEC	AX			; WRITE FIRST AND LAST LOCATION=FFFF
	SUB	DI,DI			; POINT TO START OF BLOCK
	MOV	CX,BX			; GET THE BLOCK COUNT
	SUB	CX,2			; DO ALL LOCATIONS BUT LAST
	STOSW				; WRITE FIRST LOCATION AS FFFFH
	INC	AX			; WRITE ZERO
	REP	STOSW			; WRITE IT
	DEC	AX			; LAST WORD IS FFFF
	STOSW
	SUB	SI,SI			; POINT TO START OF BLOCK
	MOV	CX,BX			; GET THE BLOCK COUNT
	SUB	CX,2
	LODSW				; GET THE DATA
	XOR	AX,0FFFFH		; CHECK CORRECT
	JNZ	C13			; EXIT IF NOT
C12A:
	LODSW				; GET NEXT DATA
	OR	AX,AX			; ANY BIT ON ?
	LOOPZ	C12A			; CONTINUE TILL LAST WORD
	JNZ	C13			; GO IF NOT CORRECT
	LODSW				; GET LAST WORD
	XOR	AX,0FFFFH		; S/B FFFF
	JNZ	C13			; EXIT IF NOT

;-----	CLEAR WORD 0 AND FFFE

	SUB	DI,DI			; CLEAR FIRST WORD
	STOSW
	MOV	DI,0FFFEH		; CLEAR TOP WORD
	STOSW

;-----	CHECK FOR I/O OR BASE MEMORY

	IN	AL,PORT_B		; CHECK FOR I/O - PARITY CHECK
	XCHG	AL,AH			; SAVE ERROR
	IN	AL,DMA_PAGE+6		; CHECK FOR R/W OR I/O ERROR
	AND	AH,AL
	MOV	AX,0			; SET AX EQUAL ZERO
	JMP	C13			; ERROR EXIT IF ZF NOT SET
STGTST_CNT	ENDP
PAGE
;------------------------------------------------------------------------
;  PRINT ADDRESS AND ERROR MESSAGE FOR ROM CHECKSUM ERRORS		:
;------------------------------------------------------------------------
ROM_ERR PROC	NEAR
	PUSH	DX			; SAVE POINTER
	PUSH	ES
	PUSH	AX
	MOV	AX,DATA 		; SET ES TO DATA SEGMENT
	MOV	ES,AX
	POP	AX			; RESTORE AX
	PUSH	AX
	MOV	DX,DS			; GET ADDRESS POINTER
	MOV	ES:@MFG_ERR_FLAG,DH	;	<><><><><><><><><><><><><><>
					;	<><> CHECKPOINTS C0->F4 <><>
	CMP	DX,0C800H		; DISPLAY CARD IN ERROR?
	JL	ROM_ERR_BEEP		; GIVE DISPLAY CARD FAIL BEEP
	CALL	PRT_SEG 		; PRINT SEGMENT IN ERROR
	MOV	SI,OFFSET F3A		; DISPLAY ERROR MESSAGE
	CALL	E_MSG
ROM_ERR_END:
	POP	AX
	POP	ES
	POP	DX
	RET
ROM_ERR_BEEP:
	MOV	DX,0102H		; BEEP 1 LONG, 2 SHORT
	CALL	ERR_BEEP
	JMP	SHORT ROM_ERR_END
ROM_ERR ENDP
;--------------------------------------------------------------------
; THIS SUBROUTINE SENDS AN OUTPUT COMMAND TO THE KEYBOARD AND	    :
;	RECEIVES THE KEYBOARD RESPONSE. 			    :
; ENTRY REQUIREMENTS:						    :
;	AL = COMMAND/DATA TO BE SENT				    :
; EXIT PARAMETERS:						    :
;	ZERO FLAG = 1 IF ACK RECEIVED FROM THE KEYBOARD 	    :
;	AL = RESPONSE						    :
;--------------------------------------------------------------------
XMIT_8042 PROC	NEAR

;-----	CHECK INPUT BUFFER FULL

	XCHG	AH,AL			; SAVE COMMAND
	SUB	CX,CX			; SET LOOP TIME-OUT
XMITLOOP:
	IN	AL,STATUS_PORT
	TEST	AL,INPT_BUF_FULL	; CHECK INPUT BUFFER FULL
	LOOPNZ	XMITLOOP
	JCXZ	SHORT XMIT_EXIT
	XCHG	AH,AL			; RESTORE COMMAND

;-----	ISSUE THE COMMAND

	OUT	PORT_A,AL		; SEND THE COMMAND
	SUB	CX,CX			; SET LOOP COUNT

;-----	CHECK OUTPUT BUFFER FULL

XMIT_1: IN	AL,STATUS_PORT
	MOV	AH,AL			; SAVE STATUS
	TEST	AL,OUT_BUF_FULL 	; CHECK IF 8042 HAS DATA
	JZ	XMIT_2			; GO IF NOT
	IN	AL,PORT_A		; FLUSH DATA
XMIT_2: TEST	AH,INPT_BUF_FULL	; CHECK COMMAND ACCEPTED
	LOOPNZ	XMIT_1
	JNZ	SHORT XMIT_EXIT 	; NO FLUSH OR COMMAND NOT ACCEPTED

;-----	CHECK OUTPUT BUFFER FULL

	MOV	BL,6			; SET COUNT
	SUB	CX,CX			; SET LOOP COUNT
XMIT_3: IN	AL,STATUS_PORT
	TEST	AL,OUT_BUF_FULL 	; CHECK IF HAS DATA
	LOOPZ	XMIT_3			; WAIT TILL DONE
	JNZ	XMIT_4
	DEC	BL			; DECREMENT OUTER LOOP
	JNZ	SHORT XMIT_3		; TRY AGAIN
	INC	BL			; SET ERROR FLAG
	JMP	SHORT XMIT_EXIT 	; 8042 STUCK BUSY

;-----	GET THE DATA

XMIT_4: SUB	CX,CX			; ALLOW TIME FOR POSSIBLE
					; ERROR -> SYSTEM UNIT OR KEYBOARD
XMIT_5: LOOP	XMIT_5
	IN	AL,PORT_A
	SUB	CX,01H			; SET CX OTHER THAN ZERO
XMIT_EXIT:
	RET
XMIT_8042 ENDP

;--- BOOT_STRAP -- INT	19H ---------------------------
; BOOT STRAP LOADER				      :
;	TRACK 0, SECTOR 1 IS READ INTO THE	      :
;	BOOT LOCATION (SEGMENT 0 OFFSET 7C00)	      :
;	AND CONTROL IS TRANSFERRED THERE.	      :
;						      :
;	IF THERE IS A HARDWARE ERROR CONTROL IS       :
;	TRANSFERRED TO THE ROM BASIC ENTRY POINT      :
;------------------------------------------------------
	ASSUME CS:CODE,DS:ABS0,ES:ABS0

BOOT_STRAP_1	PROC	NEAR

	MOV	AX,ABS0 		; ESTABLISH ADDRESSING
	MOV	DS,AX
	MOV	ES,AX

;-----	RESET THE DISK PARAMETER TABLE VECTOR

	MOV	WORD PTR @DISK_POINTER, OFFSET DISK_BASE
	MOV	WORD PTR @DISK_POINTER+2,CS

;-----	CLEAR @BOOT_LOCN

	XOR	AX,AX
	MOV	CX,256			; CLEAR 256 WORDS
	MOV	DI,OFFSET @BOOT_LOCN
	REP	STOSW

;-----	LOAD SYSTEM FROM DISKETTE -- CX HAS RETRY COUNT

	STI
	MOV	CX,4			; SET RETRY COUNT
H1:	PUSH	CX			; IPL SYSTEM
	MOV	AH,0			; RESET THE DISKETTE SYSTEM
	INT	13H			; DISKETTE_IO
	JC	H2			; IF ERROR, TRY AGAIN

	MOV	AX,201H 		; READ IN THE SINGLE SECTOR
	SUB	DX,DX			; TO THE BOOT LOCATION
	MOV	ES,DX
	MOV	BX,OFFSET @BOOT_LOCN	; DRIVE 0, HEAD 0
	MOV	CX,1			; SECTOR 1, TRACK 0
	INT	13H			; DISKETTE_IO
H2:	POP	CX			; RECOVER RETRY COUNT
	JNC	H4			; CARRY FLAG SET BY UNSUCCESSFUL READ
	CMP	AH,80H			; IF TIME OUT, NO RETRY
	JZ	H5			; TRY FIXED DISK
	LOOP	H1			; DO IT FOR RETRY TIMES
	JMP	SHORT H5		; TRY FIXED DISK

;-----	BOOT RECORD READ SUCCESSFUL
;-----	INSURE FIRST BYTE OF LOADED BOOT RECORD IS VALID (NOT ZERO)

H4:	CMP	BYTE PTR @BOOT_LOCN,06H ; CHECK FOR FIRST INSTRUCTION INVALID
	JB	H10			; IF BOOT NOT VALID PRINT MESSAGE HALT

;-----	INSURE DATA PATTERN FIRST 8 WORDS NOT ALL EQUAL

	MOV	DI,OFFSET @BOOT_LOCN	; CHECK DATA PATTERN
	MOV	CX,8			; CHECK THE NEXT 8 WORDS
	MOV	AX,WORD PTR @BOOT_LOCN

H4A:	ADD	DI,2			; POINT TO NEXT LOCATION
	CMP	AX,[DI] 		; CHECK DATA PATTERN FOR A FILL PATTERN
	LOOPZ	H4A
	JZ	H10			; BOOT NOT VALID PRINT MESSAGE HALT

H4_A:	JMP	@BOOT_LOCN

;-----	ATTEMPT BOOTSTRAP FROM FIXED DISK

H5:	MOV	AL,044H 		;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  44 <><>
	ASSUME	DS:DATA
	CALL	DDS
	TEST	@LASTRATE,DUAL		; FLOPPY/FIXED DISK CARD INSTALLED
	ASSUME	DS:ABS0
	MOV	AX,ABS0 		; ESTABLISH ADDRESSING
	MOV	DS,AX
	JZ	H9			; GO IF NOT

;-----	CHECK FOR FIXED DISK INITIALIZATION ERROR

	MOV	AL,CMOS_DIAG		; GET POST POWER ON STATUS (NMI ENABLED)
	CALL	CMOS_READ		; FROM DIAGNOSTIC STATUS BYTE
	TEST	AL,HF_FAIL		; DID WE HAVE A FIXED DISK FAILURE?
	JNZ	H9			; GO IF YES

	SUB	AX,AX			; RESET DISKETTE
	SUB	DX,DX
	INT	13H
	MOV	CX,3			; RETRY COUNT
H6:
	PUSH	CX			; SAVE RETRY COUNT
	MOV	DX,0080H		; FIXED DISK ZERO
	MOV	AX,0201H		; READ IN A SINGLE SECTOR
	SUB	BX,BX
	MOV	ES,BX
	MOV	BX,OFFSET @BOOT_LOCN	; TO THE BOOT LOCATION
	MOV	CX,1			; SECTOR 1, TRACK 0
	INT	13H			; FILE I/O CALL
	POP	CX			; RECOVER RETRY COUNT
	JC	H8
	CMP	WORD PTR @BOOT_LOCN+510D,0AA55H ; TEST FOR GENERIC BOOT BLOCK
	JZ	H4_A

H8:	PUSH	CX
	MOV	DX,0080H		; FIXED DISK ZERO
	SUB	AX,AX			; RESET THE FIXED DISK
	INT	13H			; FILE I/O CALL
	POP	CX			; RESTORE LOOP COUNT
	JC	H10A			; IF ERROR, TRY AGAIN
	LOOP	H6			; DO IT FOR RETRY TIMES

;-----	UNABLE TO IPL FROM THE DISKETTE OR FIXED DISK

H9:	MOV	AL,045H 		;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  45 <><>

	INT	18H			; GO TO RESIDENT BASIC

;-----	HARD FILE RESET FAILURE

H10A:	LOOP	H8			; TRY RESET AGAIN
	JMP	H9			; GO TO RESIDENT BASIC

;-----	IF DISKETTE READ OK BUT BOOT RECORD IS NOT STOP SYSTEM ALLOW SOFT RESET

H10:	MOV	SI,OFFSET E602		; PRINT DISKETTE BOOT
	CALL	E_MSG			; PRINT MESSAGE
H11:	JMP	H11
BOOT_STRAP_1	ENDP
POST6	ENDP
CODE	ENDS
	END
